package com.suning.sawp.service.impl.task;

import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.regex.Pattern;

import javax.annotation.Resource;

import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.poi.hssf.usermodel.HSSFCell;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.suning.sawp.constants.ConfigConstants;
import com.suning.sawp.constants.ErrorCodeConstants;
import com.suning.sawp.constants.LoggerConstants;
import com.suning.sawp.dto.common.QueryResult;
import com.suning.sawp.dto.common.ReturnMsg;
import com.suning.sawp.dto.precharge.CommonRtn;
import com.suning.sawp.dto.task.AddTaskRtn;
import com.suning.sawp.dto.task.CategoryBean;
import com.suning.sawp.dto.task.ImportExcelException;
import com.suning.sawp.dto.task.MainPushTaskRtn;
import com.suning.sawp.dto.task.QueryCommInfo;
import com.suning.sawp.dto.task.QueryRegionAssign;
import com.suning.sawp.dto.task.RegionTaskPercentBean;
import com.suning.sawp.dto.task.TaskHqInfoRtn;
import com.suning.sawp.intf.dao.task.CommTaskHqDaoService;
import com.suning.sawp.intf.dao.task.OrgRespmanDaoService;
import com.suning.sawp.intf.dao.task.RegionTaskPercentDaoService;
import com.suning.sawp.intf.dao.task.TaskHqDaoService;
import com.suning.sawp.intf.mainpush.OperationLogService;
import com.suning.sawp.intf.store.StoreInfoService;
import com.suning.sawp.intf.task.MainPushTaskManageService;
import com.suning.sawp.po.mainpush.MainPushTask;
import com.suning.sawp.po.mainpush.OptLog;
import com.suning.sawp.po.task.CommTaskHq;
import com.suning.sawp.po.task.CommTaskRegion;
import com.suning.sawp.po.task.OrgRespman;
import com.suning.sawp.po.task.RegionTaskPercent;
import com.suning.sawp.po.task.TaskHq;
import com.suning.sawp.po.task.TaskRegionPo;
import com.suning.sawp.service.task.dto.BISaleDTO;
import com.suning.sawp.service.util.BeanUtil;
import com.suning.sawp.service.util.ConfigUtil;
import com.suning.sawp.service.util.DateUtils;

@Service
public class MainPushTaskManageServiceImpl implements MainPushTaskManageService {

    @Resource
    TaskHqDaoService taskHqDaoService;

    @Resource
    RegionTaskPercentDaoService regionTaskPercentDaoService;

    @Resource
    OrgRespmanDaoService orgRespmanDaoService;

    @Resource
    CommTaskHqDaoService commTaskHqDaoService;

    @Resource
    OperationLogService operationLogService;

    @Resource
    BITaskSimpleService bITaskSimpleService;

    @Resource
    StoreInfoService storeInfoService;

    private static final Logger LOGGER = LoggerFactory.getLogger(LoggerConstants.SAWP_SERVICE);

    private static final String DATE_FORMAT = "yyyy-MM-dd";

    private static final String FULL_DATE_FORMAT = "yyyy-MM-dd HH:mm:ss";

    private static final String END_TIME_SUFFIXES = " 23:59:59";

    private static final String SEPARATOR = ",";

    private static final String CHECK_TYPE_NOTNULL = "1";

    private static final String CHECK_TYPE_PERCENT = "2";

    private static final String CHECK_TYPE_COMMCODE = "3";

    private static final String CHECK_TYPE_COMMNUM = "4";

    private static final String CHECK_TYPE_ORG = "5";

    private static final String CHECK_TYPE_COMMTYPE = "6";

    private static final String CHECK_TYPE_ORG_RESMAN = "7";

    private static final String CHECK_TYPE_NOT_NULL = "1,3,5,6";

    private static final Pattern NUM_PATTERN = Pattern.compile("[0-9]*");

    private static final Pattern NUM_SEPARATOR_PATTERN = Pattern.compile("[,0-9]*");

    @Override
    public ReturnMsg<QueryResult<MainPushTaskRtn>> queryMainPushTask(String taskTopic, String startTimeStr,
            String endTimeStr, Integer pageNo, Integer pageSize) {
        ReturnMsg<QueryResult<MainPushTaskRtn>> ret = new ReturnMsg<QueryResult<MainPushTaskRtn>>();
        QueryResult<MainPushTaskRtn> result = new QueryResult<MainPushTaskRtn>();
        Integer page = pageNo == null ? Integer.valueOf("1") : pageNo;
        Integer size = pageSize == null ? Integer.valueOf("10") : pageSize;
        // 构造查询条件
        TaskHq queryCon = new TaskHq();
        if (StringUtils.isNotBlank(taskTopic)) {
            queryCon.setTaskTopic("%" + taskTopic + "%");
        }
        if (StringUtils.isNotBlank(startTimeStr)) {
            Date startTime = DateUtils.getDateByStr(startTimeStr, DATE_FORMAT);
            queryCon.setStartTime(startTime);
        }
        if (StringUtils.isNotBlank(endTimeStr)) {
            Date endTime = DateUtils.getDateByStr(endTimeStr + END_TIME_SUFFIXES, FULL_DATE_FORMAT);
            queryCon.setEndTime(endTime);
        }
        // 查询过滤掉非正常的任务状态
        queryCon.setQueryType(0);
        int count = taskHqDaoService.queryTaskHqCount(queryCon);
        List<TaskHq> list = taskHqDaoService.queryTaskHqList(queryCon, page, size);
        List<MainPushTaskRtn> retList = new ArrayList<MainPushTaskRtn>();
        if (CollectionUtils.isNotEmpty(list)) {
            for (TaskHq task : list) {
                MainPushTaskRtn rtn = new MainPushTaskRtn();
                rtn.setTaskNo(task.getTaskNo().intValue());
                rtn.setAssignStatus(task.getAssignStatus());
                rtn.setTaskStatus(task.getTaskStatus());
                rtn.setStartTime(DateUtils.getDateStrByFormat(task.getStartTime(), DATE_FORMAT));
                rtn.setEndTime(DateUtils.getDateStrByFormat(task.getEndTime(), DATE_FORMAT));
                rtn.setTaskCreateTime(DateUtils.getLongStr(task.getCreateTime()));
                rtn.setTaskTopic(task.getTaskTopic());
                retList.add(rtn);
            }
        }
        result.setTotalSize(count);
        result.setRecords(retList);
        ret.setRetFlag(ReturnMsg.SUCCESS);
        ret.setData(result);
        return ret;
    }

    @Override
    public ReturnMsg<AddTaskRtn> addMainPushTask(String taskTopic, String startTimeStr, String endTimeStr,
            String categoryCode, String categoryName, String staffId) {

        ReturnMsg<AddTaskRtn> ret = new ReturnMsg<AddTaskRtn>();
        if (checkStr(taskTopic, startTimeStr, endTimeStr, categoryCode, categoryName)) {
            TaskHq task = new TaskHq();
            // 校验任务主题长度不能超过10
            if (taskTopic.length() > 10) {
                ret.setError(ErrorCodeConstants.MAIN_PUSH_ERR_E013, ErrorCodeConstants.MAIN_PUSH_ERR_MAP);
                return ret;
            }
            // 校验该品类在这段时间内是否已存在主推任务
            if (!checkTaskTime(startTimeStr, endTimeStr, categoryCode)) {
                ret.setError(ErrorCodeConstants.MAIN_PUSH_ERR_E015, ErrorCodeConstants.MAIN_PUSH_ERR_MAP);
                return ret;
            }
            Date startTime = DateUtils.getDateByStr(startTimeStr, DATE_FORMAT);
            Date endTime = DateUtils.getDateByStr(endTimeStr + END_TIME_SUFFIXES, FULL_DATE_FORMAT);
            task.setStartTime(startTime);
            task.setEndTime(endTime);
            task.setCategoryCode(categoryCode);
            task.setCategoryName(categoryName);
            task.setTaskTopic(taskTopic);
            task.setAssignStatus(TaskHq.AssignStatus.NO_ASSIGN);
            task.setTaskStatus(TaskHq.TaskStatus.CREATE);
            task.setTaskType(TaskHq.TaskType.MAIN_PUSH);
            task.setCreateTime(new Date());
            // 插入总部主推任务表
            Integer taskNo = taskHqDaoService.insertTask(task);
            AddTaskRtn rtn = new AddTaskRtn();
            rtn.setTaskNo(taskNo);
            ret.setRetFlag(ReturnMsg.SUCCESS);
            ret.setData(rtn);
        } else {
            ret.setError(ErrorCodeConstants.MAIN_PUSH_ERR_E002, ErrorCodeConstants.MAIN_PUSH_ERR_MAP);
        }
        return ret;
    }

    /**
     * 
     * 功能描述: 校验品类编码在该段时间内是否存在正常非删除状态的主推任务<br>
     * 〈功能详细描述〉
     *
     * @param checkTimeStart
     * @param checkTimeEnd
     * @param categoryCode
     * @return
     * @see [相关类/方法](可选)
     * @since [产品/模块版本](可选)
     */
    private boolean checkTaskTime(String checkTimeStart, String checkTimeEnd, String categoryCode) {
        TaskHq queryCon = new TaskHq();
        queryCon.setQueryType(0);
        queryCon.setCategoryCode(categoryCode);
        queryCon.setCheckTimeStart(checkTimeStart);
        queryCon.setCheckTimeEnd(checkTimeEnd);
        queryCon.setUnequalTaskStatus(TaskHq.TaskStatus.DELETE);
        return taskHqDaoService.queryTaskHqCount(queryCon) == 0;
    }

    @SuppressWarnings("unchecked")
    @Override
    public ReturnMsg<CommonRtn> importRegionPercent(Sheet sheet, Integer taskNo) {
        ReturnMsg<CommonRtn> ret = new ReturnMsg<CommonRtn>();
        // 获取sheet总行数
        int rowLength = sheet.getPhysicalNumberOfRows();
        if (rowLength > 1) {
            Map<String, Object>[] insertMaps = new Map[rowLength - 1];
            try {
                // 校验大区编码是否重复map
                Map<String, Object> checkRegion = new HashMap<String, Object>();
                for (int i = 1; i < rowLength; i++) {
                    Row row = sheet.getRow(i);
                    Map<String, Object> map = new HashMap<String, Object>();
                    // 获取大区编码，大区名称，百分比
                    String regionCode = getCellValue(row.getCell(0));
                    String regionName = getCellValue(row.getCell(1));
                    String percent = getCellValue(row.getCell(2));
                    // 校验大区编码，大区名称，百分比
                    checkCell(regionCode, i, 0, CHECK_TYPE_ORG);
                    checkCell(regionName, i, 1, CHECK_TYPE_NOTNULL);
                    checkCell(percent, i, 2, CHECK_TYPE_PERCENT);
                    if (checkRegion.get(regionCode) != null) {
                        ret.setError(ErrorCodeConstants.MAIN_PUSH_ERR_E010,
                                String.format("第%s行与第%s行大区重复,请检查", checkRegion.get(regionCode), i + 1));
                        return ret;
                    }
                    checkRegion.put(regionCode, i + 1);
                    // 校验该任务下，该大区是否已存在百分比
                    RegionTaskPercent regionPercent = regionTaskPercentDaoService.queryRegionPercent(taskNo,
                            regionCode);
                    if (regionPercent != null) {
                        ret.setError(ErrorCodeConstants.MAIN_PUSH_ERR_E011, ErrorCodeConstants.MAIN_PUSH_ERR_MAP);
                        return ret;
                    }
                    map.put("regionCode", regionCode);
                    map.put("regionName", regionName);
                    map.put("percent", StringUtils.isNotBlank(percent) ? percent : 0);
                    map.put("taskNo", taskNo);
                    insertMaps[i - 1] = map;
                }
            } catch (ImportExcelException e) {
                LOGGER.error("importRegionPercent error", e);
                ret.setError(ErrorCodeConstants.MAIN_PUSH_ERR_E010, e.getMessage());
                return ret;
            }
            // 批量插入大区占比
            regionTaskPercentDaoService.batchInsertRegionTask(insertMaps);
            ret.setRetFlag(ReturnMsg.SUCCESS);
        } else {
            ret.setError(ErrorCodeConstants.MAIN_PUSH_ERR_E008, ErrorCodeConstants.MAIN_PUSH_ERR_MAP);
        }
        return ret;
    }

    private void checkCell(String str, int i, int j, String type) throws ImportExcelException {
        if (CHECK_TYPE_NOT_NULL.contains(type) && StringUtils.isBlank(str)) {
            throw new ImportExcelException(i, j, "不能为空");
        }
        if (CHECK_TYPE_PERCENT.equals(type) && StringUtils.isNotBlank(str)) {
            if (!isNumeric(str) || Integer.parseInt(str) < 0 || Integer.parseInt(str) > 100) {
                throw new ImportExcelException(i, j, "占比必须为数字且在0-100之间");
            }
        }
        if (CHECK_TYPE_COMMCODE.equals(type)) {
            if (!NUM_SEPARATOR_PATTERN.matcher(str).matches()) {
                throw new ImportExcelException(i, j, "商品编码格式错误");
            }
            String[] split = str.split(SEPARATOR);
            if (split.length > 99) {
                throw new ImportExcelException(i, j, "商品编码集超过最大限制99");
            }
            Map<String, Object> checkCode = new HashMap<String, Object>();
            int m = 1;
            for (String s : split) {
                if (s.length() != 9) {
                    throw new ImportExcelException(i, j, "商品编码必须9位");
                }
                if (checkCode.get(s) != null) {
                    throw new ImportExcelException(i, j, String.format("第%s个与第%s个商品编码重复", checkCode.get(s), m));
                }
                checkCode.put(s, m);
                m++;
            }
        }
        if (CHECK_TYPE_COMMNUM.equals(type) && StringUtils.isNotBlank(str)) {
            if (!isNumeric(str) || Integer.valueOf(str) < 0) {
                throw new ImportExcelException(i, j, "目标台数必须为数字且大于0");
            }
        }
        if (CHECK_TYPE_ORG.equals(type)) {
            if (!isNumeric(str)) {
                throw new ImportExcelException(i, j, "必须为数字");
            }
            if (CollectionUtils.isEmpty(storeInfoService.queryStoresByRegionCode(str))) {
                throw new ImportExcelException(i, j, "大区不存在");
            }
        }
        if (CHECK_TYPE_COMMTYPE.equals(type)) {
            if (StringUtils.isBlank(str)) {
                throw new ImportExcelException(i, j, "不能为空");
            }
            if (!("A".equals(str) || "B".equals(str))) {
                throw new ImportExcelException(i, j, "商品必须为A或B类");
            }
        }
        if (CHECK_TYPE_ORG_RESMAN.equals(type)) {
            // 查询该大区是否有对接人
            OrgRespman queryCon = new OrgRespman();
            queryCon.setOrgCode(str);
            queryCon.setOrgLevel(OrgRespman.Attributes.REGION_LEVEL);
            List<OrgRespman> orgList = orgRespmanDaoService.queryOrgRespmanByCon(queryCon, null, null);
            if (CollectionUtils.isEmpty(orgList) || StringUtils.isBlank(orgList.get(0).getStaffCode())) {
                throw new ImportExcelException(i, j, "大区未分配对接人,不能分配商品");
            }
        }
    }

    private String getCellValue(Cell cell) {
        if (cell == null) {
            return "";
        }
        switch (cell.getCellType()) {
            case Cell.CELL_TYPE_FORMULA:
                return "";
            case HSSFCell.CELL_TYPE_NUMERIC:
                // 将number类型的设置成为string类型, 默认取出字符类型内容
                cell.setCellType(HSSFCell.CELL_TYPE_STRING);
                return cell.getStringCellValue().trim();
            case HSSFCell.CELL_TYPE_STRING:
                return cell.getStringCellValue().trim();
            default:
                return "";
        }
    }

    @Override
    public ReturnMsg<List<RegionTaskPercentBean>> queryRegionPercent(Integer taskNo) {
        ReturnMsg<List<RegionTaskPercentBean>> ret = new ReturnMsg<List<RegionTaskPercentBean>>();
        List<RegionTaskPercentBean> retList = new ArrayList<RegionTaskPercentBean>();
        if (taskNo != null) {
            TaskHq taskHq = taskHqDaoService.queryTaskById(taskNo);
            // 进行中的任务需要查询已完成占比，大区对接人，是否分配
            if (taskHq != null && TaskHq.TaskStatus.CARRY_ON == taskHq.getTaskStatus()) {
                retList = regionTaskPercentDaoService.queryRegionPercentInfo(taskNo);
            } else {
                retList = regionTaskPercentDaoService.queryRegionPercentList(taskNo);
            }
        }
        ret.setRetFlag(ReturnMsg.SUCCESS);
        ret.setData(retList);
        return ret;
    }

    @SuppressWarnings("unchecked")
    @Override
    @Transactional
    public ReturnMsg<CommonRtn> importRegionCommodity(Sheet sheet, Integer taskNo, String staffCode) {
        ReturnMsg<CommonRtn> ret = new ReturnMsg<CommonRtn>();
        if (taskNo == null) {
            ret.setError(ErrorCodeConstants.MAIN_PUSH_ERR_E001, ErrorCodeConstants.MAIN_PUSH_ERR_MAP);
            return ret;
        }
        int rowLength = sheet.getPhysicalNumberOfRows();
        // 获取前三行 商品信息
        // 商品类型 A,B 类
        Row row0 = sheet.getRow(0);
        // 商品型号
        Row row1 = sheet.getRow(1);
        // 商品编码集
        Row row2 = sheet.getRow(2);
        // 获取总列数
        int num = row0.getLastCellNum();
        // 商品信息从第3列开始，判断是否有商品信息
        if (num < 3) {
            ret.setError(ErrorCodeConstants.MAIN_PUSH_ERR_E014, ErrorCodeConstants.MAIN_PUSH_ERR_MAP);
            return ret;
        }
        // 根据总部任务编号查询任务信息
        TaskHq task = taskHqDaoService.queryTaskById(taskNo);
        // 查询该任务下是否已经分配商品，区分是创建任务和修改任务的商品导入
        CommTaskHq queryCon = new CommTaskHq();
        queryCon.setTaskNo(taskNo);
        boolean isExist = commTaskHqDaoService.queryCommCount(queryCon) > 0;
        // 如果是创建任务的新增商品，校验该品类在这段时间内是否已存在主推任务
        if (!isExist && !checkTaskTime(DateUtils.getDateStrByFormat(task.getStartTime(), DATE_FORMAT),
                DateUtils.getDateStrByFormat(task.getEndTime(), DATE_FORMAT), task.getCategoryCode())) {
            ret.setError(ErrorCodeConstants.MAIN_PUSH_ERR_E015, ErrorCodeConstants.MAIN_PUSH_ERR_MAP);
            return ret;
        }
        // 总部商品 key 列 value 总部商品对象
        Map<Integer, CommTaskHq> commInfoMap = new HashMap<Integer, CommTaskHq>();
        // 大区任务 key 行 value 大区任务对象
        Map<Integer, TaskRegionPo> taskRegionMap = new HashMap<Integer, TaskRegionPo>();
        // 大区商品 key 行,列 value 大区商品对象
        Map<String, CommTaskRegion> commRegionMap = new HashMap<String, CommTaskRegion>();
        // 每个商品总台数 key 列 value 商品总目标台数
        Map<Integer, Integer> destNumHq = new HashMap<Integer, Integer>();
        // 日志内容
        StringBuilder logComm = new StringBuilder("新增商品:");
        try {
            // 判断每列之间商品型号是否重复
            Map<String, Object> checkComm = new HashMap<String, Object>();
            // 遍历检查每列商品信息
            for (int i = 2; i < num; i++) {
                CommTaskHq comm = new CommTaskHq();
                comm.setAssignStatus(CommTaskHq.commAssignStatus.NO_ASSIGN);
                comm.setCommStatus(CommTaskHq.commStatusEnum.NORMAL);
                // 获取商品类型 商品型号 商品编码集
                String commType = getCellValue(row0.getCell(i));
                String commName = getCellValue(row1.getCell(i));
                String commCodes = getCellValue(row2.getCell(i));
                // 校验 商品类型 商品型号 商品编码集
                checkCell(commType, 0, i, CHECK_TYPE_COMMTYPE);
                checkCell(commCodes, 2, i, CHECK_TYPE_COMMCODE);
                checkCell(commName, 1, i, CHECK_TYPE_NOTNULL);
                // 判断每列之间商品型号是否重复
                if (checkComm.get(commName) != null) {
                    ret.setError(ErrorCodeConstants.MAIN_PUSH_ERR_E010,
                            String.format("第%s列与第%s列型号重复,请检查", checkComm.get(commName), i + 1));
                    return ret;
                }
                checkComm.put(commName, i + 1);
                comm.setCommType(commType);
                comm.setCommName(commName);
                comm.setCommCodes(commCodes);
                comm.setTaskNo(taskNo);
                comm.setCategoryCode(task.getCategoryCode());
                // 如果任务下已存在商品，判断商品名称是否已存在
                if (isExist) {
                    logComm.append(comm.getCommName()).append(SEPARATOR);
                    queryCon.setCommName(comm.getCommName());
                    if (commTaskHqDaoService.queryCommCount(queryCon) > 0) {
                        ret.setError(ErrorCodeConstants.MAIN_PUSH_ERR_E009, String.format("第2行,第%s列型号已存在", i + 1));
                        return ret;
                    }
                }
                commInfoMap.put(i, comm);
            }
            // 校验每行大区编码是否重复
            Map<String, Object> checkRegion = new HashMap<String, Object>();
            // 判断是否已经判断过大区对接人
            Map<String, Object> checkOrgResman = new HashMap<String, Object>();
            // 检查大区信息和大区每个型号目标台数
            for (int i = 3; i < rowLength; i++) {
                TaskRegionPo taskRegion = new TaskRegionPo();
                String orgCode = getCellValue(sheet.getRow(i).getCell(0));
                String orgName = getCellValue(sheet.getRow(i).getCell(1));
                if (checkRegion.get(orgCode) != null) {
                    ret.setError(ErrorCodeConstants.MAIN_PUSH_ERR_E010,
                            String.format("第%s行与第%s行大区重复,请检查", checkRegion.get(orgCode), i + 1));
                    return ret;
                }
                checkRegion.put(orgCode, i + 1);
                task.setUpdateTime(new Date());
                BeanUtil.copyProperties(taskRegion, task);
                // 校验大区编码和大区名称
                checkCell(orgCode, i, 0, CHECK_TYPE_ORG);
                checkCell(orgName, i, 1, CHECK_TYPE_NOTNULL);
                taskRegion.setOrgCode(orgCode);
                taskRegion.setOrgName(orgName);
                taskRegion.setParTaskNo(taskNo);
                taskRegion.setTaskStatus(TaskHq.TaskStatus.NO_BEGIN);
                taskRegion.setAssignStatus(TaskHq.AssignStatus.NO_ASSIGN);
                taskRegion.setCreateTime(new Date());
                taskRegion.setUpdateTime(new Date());
                taskRegionMap.put(i, taskRegion);
                for (int j = 2; j < num; j++) {
                    CommTaskRegion commRegion = new CommTaskRegion();
                    String regionDestNum = getCellValue(sheet.getRow(i).getCell(j));
                    // 校验大区目标台数
                    checkCell(regionDestNum, i, j, CHECK_TYPE_COMMNUM);
                    CommTaskHq commTaskHq = commInfoMap.get(j);
                    BeanUtil.copyProperties(commRegion, commTaskHq);
                    // 如果是已存在任务新增商品，大区商品状态设置为高亮
                    if (isExist) {
                        commRegion.setCommStatus(CommTaskHq.commStatusEnum.REGION_HIGHLIGHT);
                    }
                    if (StringUtils.isNotBlank(regionDestNum) && !"0".equals(regionDestNum)) {
                        if (checkOrgResman.get(orgCode) == null) {
                            // 校验大区对接人是否存在
                            checkCell(orgCode, i, 1, CHECK_TYPE_ORG_RESMAN);
                            checkOrgResman.put(orgCode, 1);
                        }
                        commRegion.setDestNum(Integer.valueOf(regionDestNum));
                        commRegionMap.put(String.valueOf(i) + SEPARATOR + String.valueOf(j), commRegion); 
                        Integer destNum = destNumHq.get(j) == null ? Integer.valueOf("0") : destNumHq.get(j);
                        destNumHq.put(j, destNum + commRegion.getDestNum());
                    }
                }
            }
        } catch (Exception e) {
            LOGGER.error("importRegionCommodity error", e);
            ret.setError(ErrorCodeConstants.MAIN_PUSH_ERR_E010, e.getMessage());
            return ret;
        }
        Map<Integer, Integer> regionTaskNos = new HashMap<Integer, Integer>();
        // 新增或查询 大区任务表
        for (Entry<Integer, TaskRegionPo> entry : taskRegionMap.entrySet()) {
            TaskRegionPo region = entry.getValue();
            Integer regionTaskNo = null;
            // 如果是非创建任务，新增商品，大区任务已存在，直接查询大区任务编码
            if (isExist) {
                regionTaskNo = commTaskHqDaoService.queryRegionTaskNo(taskNo, region.getOrgCode());
                commTaskHqDaoService.updateRegionTaskStatus(TaskHq.AssignStatus.EDIT_ASSIGN, regionTaskNo);
            }
            // 如果是创建任务导入商品，新增大区任务
            if (regionTaskNo == null) {
                region.setTaskNo(null);
                regionTaskNo = taskHqDaoService.insertTaskRegion(region);
            }
            regionTaskNos.put(entry.getKey(), regionTaskNo);
        }
        // 新增总部商品表信息
        Map<Integer, Integer> commClassifyCodes = new HashMap<Integer, Integer>();
        for (Entry<Integer, CommTaskHq> entry : commInfoMap.entrySet()) {
            CommTaskHq value = entry.getValue();
            Integer destNum = destNumHq.get(entry.getKey()) == null ? 0 : destNumHq.get(entry.getKey());
            // 如果商品的总目标台数大于0，总部商品状态为已分配
            if (destNum > 0) {
                value.setAssignStatus(CommTaskHq.commAssignStatus.ASSIGNED);
            }
            value.setDestNum(destNumHq.get(entry.getKey()));
            // 插入总部商品表
            Integer commClassifyCode = commTaskHqDaoService.insertCommTask(value);
            commClassifyCodes.put(entry.getKey(), commClassifyCode);
        }
        // 如果是创建任务，并且新增商品成功，修改任务状态为未开始，之前是-1，非正常状态
        if (!commClassifyCodes.isEmpty() && !isExist) {
            TaskHq taskupdate = new TaskHq();
            taskupdate.setTaskStatus(TaskHq.TaskStatus.NO_BEGIN);
            taskHqDaoService.updateTask(taskupdate, taskNo);
            // 记录操作日志
            OptLog log = new OptLog();
            log.setOptOrgLevel(MainPushTask.OrgLevelConstants.LEVEL_HQ);
            log.setOptType(OptLog.OptTypeConstants.TYPE_ADD);
            log.setOptStaffCode(staffCode);
            log.setTaskNo(Long.valueOf(taskNo));
            StringBuilder content = new StringBuilder("创建主推任务:").append(task.getTaskTopic()).append(",品类:")
                    .append(task.getCategoryName());
            log.setOptContent(content.toString());
            operationLogService.log(log);
        }
        // 判断是否修改任务分配状态 如果该任务下不存在未分配的商品，总部任务状态改为已分配
        isUpdateTaskStatus(taskNo);
        Map<String, Object>[] insertCommRegionMaps = new Map[commRegionMap.size()];
        int q = 0;
        // 新增大区商品表数据
        for (Entry<String, CommTaskRegion> entry : commRegionMap.entrySet()) {
            String key = entry.getKey();
            String[] split = key.split(SEPARATOR);
            // 获取目标台数对应的大区任务编码和商品归类编码
            Integer regionTaskNo = regionTaskNos.get(Integer.valueOf(split[0]));
            Integer commClassifyCode = commClassifyCodes.get(Integer.valueOf(split[1]));
            Map<String, Object> map = new HashMap<String, Object>();
            CommTaskRegion value = entry.getValue();
            value.setId(null);
            value.setTaskNo(regionTaskNo);
            value.setCommClassifyCode(commClassifyCode);
            map.putAll(BeanUtil.describe(value));
            insertCommRegionMaps[q] = map;
            q++;
        }
        // 批量插入大区商品表
        if (insertCommRegionMaps.length > 0) {
            commTaskHqDaoService.batchInsertRegionComm(insertCommRegionMaps);
        }
        // 如果是非创建任务，新增商品，记录日志
        if (isExist) {
            OptLog log = new OptLog();
            log.setOptStaffCode(staffCode);
            log.setOptOrgLevel(MainPushTask.OrgLevelConstants.LEVEL_HQ);
            log.setOptType(OptLog.OptTypeConstants.TYPE_ADD);
            log.setTaskNo(Long.valueOf(taskNo));
            log.setOptContent(logComm.toString().substring(0, logComm.toString().length() - 1));
            operationLogService.log(log);
        }
        ret.setRetFlag(ReturnMsg.SUCCESS);
        return ret;
    }

    @Override
    public ReturnMsg<QueryResult<QueryCommInfo>> queryCommInfoHq(Integer taskNo, Integer pageNo, Integer pageSize) {
        ReturnMsg<QueryResult<QueryCommInfo>> ret = new ReturnMsg<QueryResult<QueryCommInfo>>();
        QueryResult<QueryCommInfo> result = new QueryResult<QueryCommInfo>();
        List<QueryCommInfo> retList = new ArrayList<QueryCommInfo>();
        Integer page = pageNo == null ? Integer.valueOf("1") : pageNo;
        Integer size = pageSize == null ? Integer.valueOf("10") : pageSize;
        CommTaskHq queryCon = new CommTaskHq();
        queryCon.setTaskNo(taskNo);
        int count = commTaskHqDaoService.queryCommCount(queryCon);
        List<CommTaskHq> list = commTaskHqDaoService.queryCommList(queryCon, page, size);
        if (CollectionUtils.isNotEmpty(list)) {
            for (CommTaskHq comm : list) {
                QueryCommInfo queryComm = new QueryCommInfo();
                BeanUtil.copyProperties(queryComm, comm);
                retList.add(queryComm);
            }
        }
        result.setTotalSize(count);
        result.setRecords(retList);
        ret.setRetFlag(ReturnMsg.SUCCESS);
        ret.setData(result);
        return ret;
    }

    @Override
    public ReturnMsg<List<QueryRegionAssign>> queryRegionAssign(Integer commClassifyCode, Integer taskNo) {
        ReturnMsg<List<QueryRegionAssign>> ret = new ReturnMsg<List<QueryRegionAssign>>();
        List<QueryRegionAssign> list = new ArrayList<QueryRegionAssign>();
        if (commClassifyCode != null && taskNo != null) {
            list = commTaskHqDaoService.queryCommRegionAssign(commClassifyCode, taskNo);
        }
        ret.setRetFlag(ReturnMsg.SUCCESS);
        ret.setData(list);
        return ret;
    }

    private boolean checkStr(String... args) {
        for (String s : args) {
            if (StringUtils.isBlank(s)) {
                return false;
            }
        }
        return true;
    }

    @Transactional
    @Override
    public ReturnMsg<CommonRtn> updateCommHqDestNum(List<String> list, Integer taskNo) {
        ReturnMsg<CommonRtn> ret = new ReturnMsg<CommonRtn>();
        if (CollectionUtils.isNotEmpty(list) && taskNo != null) {
            List<String> commList = commTaskHqDaoService.queryCommIdAndDestnum(taskNo);
            list.removeAll(commList);
            @SuppressWarnings("unchecked")
            Map<String, Object>[] paramMaps = new Map[list.size()];
            if (CollectionUtils.isNotEmpty(list)) {
                int i = 0;
                for (String commInfo : list) {
                    String[] split = commInfo.split(SEPARATOR);
                    Map<String, Object> paramMap = new HashMap<String, Object>();
                    paramMap.put("assignStatus", CommTaskHq.commAssignStatus.UPDATE);
                    paramMap.put("destNum", Integer.valueOf(split[1]));
                    paramMap.put("commClassifyCode", Integer.valueOf(split[0]));
                    paramMaps[i] = paramMap;
                    i++;
                }
                commTaskHqDaoService.batchUpdate(paramMaps);
                ret.setRetFlag(ReturnMsg.SUCCESS);
            }
        } else {
            ret.setError(ErrorCodeConstants.MAIN_PUSH_ERR_E001, ErrorCodeConstants.MAIN_PUSH_ERR_MAP);
        }
        return ret;
    }

    @SuppressWarnings("unchecked")
    @Transactional
    @Override
    public ReturnMsg<CommonRtn> updateCommRegionDestNum(List<String> list, Integer commClassifyCode, Integer destNumHq,
            String staffId) {
        ReturnMsg<CommonRtn> ret = new ReturnMsg<CommonRtn>();
        // 入参list string 为 大区商品表Id，大区编码，大区任务编码，目标台数 逗号拼接
        if (CollectionUtils.isEmpty(list) || commClassifyCode == null) {
            ret.setError(ErrorCodeConstants.MAIN_PUSH_ERR_E001, ErrorCodeConstants.MAIN_PUSH_ERR_MAP);
            return ret;
        }
        // 查询数据库中的大区商品分配列表 string 为大区商品表Id，大区编码，大区任务编码，目标台数 逗号拼接
        List<String> commList = commTaskHqDaoService.queryRegionCommIdAndDestnum(commClassifyCode);
        // 创建old list 存放数据中修改之前的数据，方便记录日志
        List<String> commOldList = new ArrayList<String>();
        commOldList.addAll(commList);
        // 去除请求list中相同的数据，剩下的是需要更新的数据
        commOldList.removeAll(list);
        // 去除数据库中查出的相同的数据
        list.removeAll(commList);
        // 查询商品信息
        CommTaskHq commHq = commTaskHqDaoService.queryCommTaskHq(commClassifyCode);
        if (commHq == null) {
            ret.setError(ErrorCodeConstants.MAIN_PUSH_ERR_E003, ErrorCodeConstants.MAIN_PUSH_ERR_MAP);
            return ret;
        }
        // 日志Map数组
        Map<String, String>[] logMaps = new Map[list.size()];
        // 批量修改的map数组
        Map<String, Object>[] updateMaps = new Map[commOldList.size()];
        if (CollectionUtils.isEmpty(list)) {
            ret.setRetFlag(ReturnMsg.SUCCESS);
            return ret;
        }
        int j = 0;
        int k = 0;
        for (String commInfo : list) {
            String[] split = commInfo.split(SEPARATOR);
            Map<String, String> logMap = new HashMap<String, String>();
            // 如果之前从来没有分配过目标台数，并且本次也未修改，直接跳过
            if (StringUtils.isBlank(split[0]) && split.length < 4) {
                continue;
            }
            // 校验目标台数
            if (split.length > 3 && (!isNumeric(split[3].trim()) || Integer.valueOf(split[3].trim()) < 0)) {
                ret.setError(ErrorCodeConstants.MAIN_PUSH_ERR_E001, "大区:" + split[1] + "目标台数非数字或小于0");
                return ret;
            }
            // 判断是否有ID，存在为修改，不存在为新增
            if (StringUtils.isBlank(split[0]) && StringUtils.isNotBlank(split[1])) {
                CommTaskRegion commRegion = new CommTaskRegion();
                BeanUtil.copyProperties(commRegion, commHq);
                commRegion.setTaskNo(Integer.valueOf(split[2]));
                commRegion.setDestNum(Integer.valueOf(split[3].trim()));
                commRegion.setAssignStatus(CommTaskHq.commAssignStatus.NO_ASSIGN);
                commRegion.setCommStatus(CommTaskHq.commStatusEnum.REGION_HIGHLIGHT);
                commRegion.setId(null);
                // 增加判断商品是否已经分配，避免前台重复提交
                if (commTaskHqDaoService.isCommRegionExist(commRegion.getTaskNo(), commClassifyCode)) {
                    continue;
                }
                // 新增大区商品数据
                commTaskHqDaoService.insertCommRegion(commRegion);
                // 修改大区分配状态为修改待分配
                commTaskHqDaoService.updateRegionTaskStatus(TaskHq.AssignStatus.EDIT_ASSIGN, commRegion.getTaskNo());
            } else {
                Map<String, Object> updateMap = new HashMap<String, Object>();
                updateMap.put("destNum", split.length == 3 ? 0 : Integer.parseInt(split[3].trim()));
                updateMap.put("assignStatus", CommTaskHq.commAssignStatus.UPDATE);
                updateMap.put("commStatus", CommTaskHq.commStatusEnum.REGION_HIGHLIGHT);
                updateMap.put("Id", Integer.valueOf(split[0]));
                logMap.put("Id", split[0]);
                updateMaps[j] = updateMap;
                j++;
            }
            logMap.put("destNum", split.length == 3 ? "0" : split[3].trim());
            logMap.put("orgCode", split[1]);
            logMaps[k] = logMap;
            k++;
        }
        // 批量修改大区商品目标台数
        if (updateMaps.length > 0) {
            commTaskHqDaoService.batchUpdateRegionComm(updateMaps);
        }
        // 判断总目标台数是否变化，如果发生变化，修改总部商品信息
        if (!destNumHq.equals(commHq.getDestNum())) {
            CommTaskHq commtaskHq = new CommTaskHq();
            commtaskHq.setDestNum(destNumHq);
            commTaskHqDaoService.updateCommById(commtaskHq, commClassifyCode);
            isUpdateTaskStatus(commHq.getTaskNo());
        }
        Map<String, String> commOld = new HashMap<String, String>();
        for (String s : commOldList) {
            String[] split = s.split(SEPARATOR);
            commOld.put(split[0], split[3]);
        }
        // 记录操作日志
        logOperate(logMaps, commOld, commHq.getTaskNo(), staffId, 1, commHq.getCommName());
        ret.setRetFlag(ReturnMsg.SUCCESS);
        return ret;
    }

    private static boolean isNumeric(String str) {
        if (!NUM_PATTERN.matcher(str).matches()) {
            return false;
        }
        return true;
    }

    /**
     * 
     * 功能描述: 判断是否大区下是否所有商品已分配<br>
     * 〈功能详细描述〉
     *
     * @param taskNo
     * @see [相关类/方法](可选)
     * @since [产品/模块版本](可选)
     */
    private void isUpdateTaskStatus(Integer taskNo) {
        if (commTaskHqDaoService.isAssignAllComm(taskNo)) {
            TaskHq taskupdate = new TaskHq();
            taskupdate.setAssignStatus(TaskHq.AssignStatus.ASSIGNED);
            taskHqDaoService.updateTask(taskupdate, taskNo);
        }
    }

    @Transactional
    @SuppressWarnings("unchecked")
    @Override
    public ReturnMsg<CommonRtn> updatePercent(List<String> list, Integer taskNo, String staffId) {
        ReturnMsg<CommonRtn> ret = new ReturnMsg<CommonRtn>();
        if (CollectionUtils.isNotEmpty(list)) {
            List<String> listPercent = regionTaskPercentDaoService.queryRegionPercent(taskNo);
            List<String> oldPercent = new ArrayList<String>();
            oldPercent.addAll(listPercent);
            oldPercent.removeAll(list);
            list.removeAll(listPercent);
            Map<String, Object>[] paramMaps = new Map[list.size()];
            Map<String, String>[] logMaps = new Map[list.size()];
            int i = 0;
            if (CollectionUtils.isEmpty(list)) {
                ret.setRetFlag(ReturnMsg.SUCCESS);
                return ret;
            }
            for (String s : list) {
                String[] split = s.split(SEPARATOR);
                Map<String, Object> paramMap = new HashMap<String, Object>();
                Map<String, String> logMap = new HashMap<String, String>();
                String percent = split[2].trim();
                if (!isNumeric(percent) || Integer.parseInt(percent) < 0 || Integer.parseInt(percent) > 100) {
                    ret.setError(ErrorCodeConstants.MAIN_PUSH_ERR_E001, "大区:" + split[1] + "目标占比非数字或不在0-100以内");
                    return ret;
                }
                paramMap.put("percent", percent);
                paramMap.put("condition_Id", split[0]);
                paramMaps[i] = paramMap;
                logMap.put("Id", split[0]);
                logMap.put("orgCode", split[1]);
                logMap.put("percent", percent);
                logMaps[i] = logMap;
                i++;
            }
            regionTaskPercentDaoService.batchUpdate(paramMaps);
            Map<String, String> oldPercentMap = new HashMap<String, String>();
            for (String s : oldPercent) {
                String[] split = s.split(SEPARATOR);
                oldPercentMap.put(split[0], split[2]);
            }
            logOperate(logMaps, oldPercentMap, taskNo, staffId, 2, null);
            ret.setRetFlag(ReturnMsg.SUCCESS);
        } else {
            ret.setError(ErrorCodeConstants.MAIN_PUSH_ERR_E001, ErrorCodeConstants.MAIN_PUSH_ERR_MAP);
        }
        return ret;
    }

    private void logOperate(Map<String, String>[] logMaps, Map<String, String> oldMap, Integer taskNo, String staffId,
            Integer type, String commName) {
        try {
            for (Map<String, String> map : logMaps) {
                if (map == null) {
                    continue;
                }
                OptLog log = new OptLog();
                log.setOptOrgLevel(MainPushTask.OrgLevelConstants.LEVEL_HQ);
                log.setOptType(OptLog.OptTypeConstants.TYPE_UPDATE);
                log.setOptStaffCode(staffId);
                log.setTaskNo(Long.valueOf(taskNo));
                StringBuilder content = new StringBuilder();
                if (type == 1) {
                    content.append("商品型号:").append(commName).append(",分配大区:").append(map.get("orgCode"))
                            .append(",分配数量:");
                    if (map.get("Id") != null) {
                        String oldDestNum = oldMap.get(map.get("Id")) == null ? "0" : oldMap.get(map.get("Id"));
                        content.append(oldDestNum).append("→").append(map.get("destNum"));
                    } else {
                        content.append("0→").append(map.get("destNum"));
                    }
                }
                if (type == 2) {
                    String prePercent = oldMap.get(map.get("Id"));
                    String percent = map.get("percent");
                    content.append("总部任务编号:").append(taskNo).append(",分配大区:").append(map.get("orgCode"))
                            .append(",修改目标占比:").append(StringUtils.isBlank(prePercent) ? "0" : prePercent).append("%→")
                            .append(StringUtils.isBlank(percent) ? "0" : percent).append("%");
                }
                log.setOptContent(content.toString());
                operationLogService.log(log);
            }
        } catch (Exception e) {
            LOGGER.error("操作日志记录失败", e);
        }
    }

    @Override
    public ReturnMsg<CommonRtn> deleteTaskByTaskNo(Integer taskNo, String taskTopic, String staffId) {
        ReturnMsg<CommonRtn> ret = new ReturnMsg<CommonRtn>();
        if (taskNo != null) {
            taskHqDaoService.softDeleteTaskByTaskNo(taskNo);
            OptLog log = new OptLog();
            log.setOptOrgLevel(MainPushTask.OrgLevelConstants.LEVEL_HQ);
            log.setOptType(OptLog.OptTypeConstants.TYPE_DELETE);
            log.setOptStaffCode(staffId);
            log.setTaskNo(Long.valueOf(taskNo));
            StringBuilder content = new StringBuilder("删除总部任务,任务:").append(taskTopic);
            log.setOptContent(content.toString());
            operationLogService.log(log);
            ret.setRetFlag(ReturnMsg.SUCCESS);
        } else {
            ret.setError(ErrorCodeConstants.MAIN_PUSH_ERR_E001, ErrorCodeConstants.MAIN_PUSH_ERR_MAP);
        }
        return ret;
    }

    @Override
    public ReturnMsg<CommonRtn> deleteCommBycommCode(Integer commClassifyCode, String commName, String staffId) {
        ReturnMsg<CommonRtn> ret = new ReturnMsg<CommonRtn>();
        if (commClassifyCode != null) {
            commTaskHqDaoService.softDeleteComm(commClassifyCode);
            CommTaskHq comm = commTaskHqDaoService.queryCommTaskHq(commClassifyCode);
            isUpdateTaskStatus(comm.getTaskNo());
            OptLog log = new OptLog();
            log.setOptOrgLevel(MainPushTask.OrgLevelConstants.LEVEL_HQ);
            log.setOptType(OptLog.OptTypeConstants.TYPE_DELETE);
            log.setOptStaffCode(staffId);
            log.setTaskNo(Long.valueOf(comm.getTaskNo()));
            StringBuilder content = new StringBuilder("删除商品,型号:").append(commName);
            log.setOptContent(content.toString());
            operationLogService.log(log);
            ret.setRetFlag(ReturnMsg.SUCCESS);
        } else {
            ret.setError(ErrorCodeConstants.MAIN_PUSH_ERR_E001, ErrorCodeConstants.MAIN_PUSH_ERR_MAP);
        }
        return ret;
    }

    @Override
    public ReturnMsg<TaskHqInfoRtn> queryTaskHqInfo(Integer taskNo) {
        ReturnMsg<TaskHqInfoRtn> ret = new ReturnMsg<TaskHqInfoRtn>();
        if (taskNo != null) {
            TaskHq task = taskHqDaoService.queryTaskById(taskNo);
            if (task != null) {
                TaskHqInfoRtn rtn = new TaskHqInfoRtn();
                rtn.setTaskTopic(task.getTaskTopic());
                rtn.setCategoryName(task.getCategoryName());
                rtn.setTaskStatus(task.getTaskStatus());
                rtn.setStartTime(DateUtils.getDateStrByFormat(task.getStartTime(), DATE_FORMAT));
                rtn.setEndTime(DateUtils.getDateStrByFormat(task.getEndTime(), DATE_FORMAT));
                if (TaskHq.TaskStatus.CARRY_ON == task.getTaskStatus()) {
                    BISaleDTO dto = bITaskSimpleService.sumBIDis(taskNo);
                    if (dto != null && dto.getSaleAmount() != null) {
                        rtn.setSaleAmount(String.format("%s元", dto.getSaleAmount().toString()));
                    }
                }
                ret.setRetFlag(ReturnMsg.SUCCESS);
                ret.setData(rtn);
            } else {
                ret.setError(ErrorCodeConstants.MAIN_PUSH_ERR_E004, ErrorCodeConstants.MAIN_PUSH_ERR_MAP);
            }
        } else {
            ret.setError(ErrorCodeConstants.MAIN_PUSH_ERR_E001, ErrorCodeConstants.MAIN_PUSH_ERR_MAP);
        }
        return ret;
    }

    @Override
    public ReturnMsg<List<CategoryBean>> queryCategoryList() {
        ReturnMsg<List<CategoryBean>> ret = new ReturnMsg<List<CategoryBean>>();
        List<CategoryBean> list = new ArrayList<CategoryBean>();
        Map<String, String> cateMap = ConfigUtil.getConfigMap(ConfigConstants.SAWP_CONFIG_MAIN_PUSH_CATEGORY,
                ConfigConstants.DEFAULT_CATE_MAP);
        if (cateMap != null && !cateMap.isEmpty()) {
            for (Entry<String, String> entry : cateMap.entrySet()) {
                CategoryBean bean = new CategoryBean();
                bean.setCategoryCode(entry.getKey());
                bean.setCategoryName(entry.getValue());
                list.add(bean);
            }
        }
        ret.setRetFlag(ReturnMsg.SUCCESS);
        ret.setData(list);
        return ret;
    }

}
